import React, { forwardRef, createElement, useEffect } from "react"
import { isObject, isFunction } from "@/utils"
import useSetState from "@/hooks/useSetState"
import useSetRef from "@/hooks/useSetRef"
import { IconCopy, IconSuccessFilling, IconEdit } from "../icon/index"
import EditContent from "./EditContent"
const getClassNameAndComponentName = (props, prefixCls) => {
    const { className, type, disabled, spacing, bold, mark, underline, delete: propDelete, code, blockquote } = props
    const component = []
    const _className = []
    if (type) {
        _className.push(`${prefixCls}-${type}`)
    }
    if (disabled) {
        _className.push(`${prefixCls}-disabled`)
    }
    if (spacing) {
        _className.push(`${prefixCls}-spacing-${spacing}`)
    }
    if (className) {
        _className.push(className)
    }
    if (bold) {
        component.push("b")
    }
    if (underline) {
        component.push("u")
    }
    if (propDelete) {
        component.push("del")
    }
    if (code) {
        component.push("code")
    }
    if (mark) {
        component.push("mark")
    }
    if (blockquote) {
        component.push("blockquote")
    }
    return {
        component,
        className: _className.join(" ")
    }
}
const Base = (props, ref) => {
    const {
        heading,
        componentType,
        mark,
        children,
        copyable,
        editable,
        key,
        style
    } = props
    const [state, setState] = useSetState({
        isCopySuccess: false,
        isEditing: false
    })
    const [_ref, setRef] = useSetRef({
        style: {},
        elementRef: null
    })
    const { component, className } = getClassNameAndComponentName(props, "next-typography")
    const editableConfig = isObject(editable) ? editable : {}
    useEffect(() => {
        onMounted()
    }, [])
    const onMounted = () => {
        if (!_ref.elementRef) return
        const styles = window.getComputedStyle(_ref.elementRef)
        const fontSize = styles.fontSize
        const fontWeight = styles.fontWeight
        const style = {
            fontSize,
            fontWeight
        }
        setRef({ style })
    }
    const onCopy = async () => {
        const permission = await navigator.permissions.query({ name: 'clipboard-write' });
        if (["granted", "prompt"].includes(permission.state)) {
            await navigator.clipboard.writeText(children);
        } else {
            const textarea = document.createElement('textarea');
            textarea.value = children;
            document.body.appendChild(textarea);
            textarea.select();
            try {
                document.execCommand('copy');
            } catch (err) {
                console.error('无法复制文本: ', err);
            } finally {
                document.body.removeChild(textarea);
            }
        }
        setState({ isCopySuccess: true })
        const timer = setTimeout(() => {
            setState({ isCopySuccess: false })
            clearTimeout(timer)
        }, 1500)
        isFunction(copyable) && copyable(children)
    }
    const onUpdateEditing = (isEditing) => {
        setState({ isEditing })
    }
    const onClickOperation = () => {
        if (copyable) {
            return onCopy()
        }
        onUpdateEditing(true)
    }
    const renderContent = () => {
        if (!component.length) {
            return children
        }
        const _props = isObject(mark) && mark.color ? { style: { backgroundColor: mark.color } } : {}
        let content
        component.forEach(c => {
            content = createElement(c, _props, content || children)
        })
        return content
    }
    const renderIcon = () => {
        if (!copyable && !editable) return null
        const label = editable ? "编辑" : "复制"
        return (
            <span onClick={onClickOperation} role="button" aria-label={label} className="next-typography-operation-copy">
                {copyable ? state.isCopySuccess ? <IconSuccessFilling style={{ color: "var(--color-success-6)" }} /> : <IconCopy /> : null}
                {editable && <IconEdit />}
            </span>
        )
    }
    const renderChildren = () => {
        return (
            <>
                {renderContent()}
                {renderIcon()}
            </>
        )
    }
    const mergeRef = (r) => {
        setRef({ elementRef: r })
        if (isObject(ref) && "current" in ref) {
            ref.current = r
        }
        isFunction(ref) && ref(r)
    }
    const _props = {
        key,
        ref: mergeRef,
        className: `next-typography ${className}`,
        style
    }
    const ComponentMap = {
        Title: `h${heading}`,
        Text: "span",
        Paragraph: "div"
    }
    const type = ComponentMap[componentType]
    if (state.isEditing) {
        return <EditContent
            {...props}
            ref={ref}
            className={className}
            setEditing={onUpdateEditing}
            editableConfig={editableConfig}
            style={_ref.style}
        />
    }
    return createElement(type, _props, renderChildren())
}
export default forwardRef(Base)